package cn.buk.tms.dao;

import cn.buk.tms.entity.order.vas.VasOrderPassenger_;
import cn.buk.tms.entity.order.vas.VasOrder_;
import cn.buk.tms.factory.OperationLogFactory;
import cn.buk.tms.sc.SearchFlightOrderCriteria;
import cn.buk.tms.common.constant.TmsOrderConstant;
import cn.buk.common.util.DateUtil;

import java.util.ArrayList;
import java.util.List;

import jakarta.persistence.criteria.*;
import jakarta.transaction.Transactional;

import cn.buk.tms.entity.misc.OperationLog;
import cn.buk.tms.entity.misc.PaymentMethod;
import cn.buk.tms.entity.misc.Supplier;
import cn.buk.tms.entity.misc.TieInProduct;
import cn.buk.tms.entity.order.flight.FlightOrder;
import cn.buk.tms.entity.order.flight.FlightOrderExtra;
import cn.buk.tms.entity.order.vas.VasOrder;
import cn.buk.tms.entity.order.vas.VasOrderPassenger;
import org.springframework.stereotype.Component;

import static cn.buk.tms.common.constant.TmsOrderConstant.OPERATING_OBJECT_VAS_ORDER;

/**
 * @author yfdai
 */
@Component
@Transactional
public class VasOrderDaoImpl extends AbstractDao implements VasOrderDao {

  @Override
  public int createVasOrder(VasOrder o) {
    int retCode;


    em.persist(o);

    OperationLog log = OperationLogFactory.createVasOrderOperationLog();
    log.setEnterpriseId(o.getEnterpriseId());
    log.setOrderId(o.getId());
    log.setOperator(o.getOperator());
    log.setContent("创建订单");

    em.persist(log);

    if (o.getFlightOrderId() > 0) {
      // 需要关联订单
      FlightOrder flightOrder = em.find(FlightOrder.class, o.getFlightOrderId());
      if (flightOrder != null && flightOrder.getEnterpriseId() == o.getEnterpriseId()) {
        FlightOrderExtra extra = new FlightOrderExtra();
        extra.setEnterpriseId(o.getEnterpriseId());
        extra.setOrder(flightOrder);
        extra.setVasOrderId(o.getId());
        extra.setProductCode(o.getProductCode());
        extra.setProductName(o.getProductName());

        em.persist(extra);

        OperationLog log1 = OperationLogFactory.createFlightOrderOperationLog();
        log1.setEnterpriseId(o.getEnterpriseId());
        log1.setOrderId(o.getFlightOrderId());
        log1.setOperator(o.getOperator());
        log1.setContent("关联服务订单");

        em.persist(log1);
      }
    }


    retCode = o.getId();

    return retCode;
  }

  @Override
  public VasOrder getOrderById(int id) {

    VasOrder order = em.find(VasOrder.class, id);
    if (order == null) {
      throw new RuntimeException("VasOrder(" + id + ") is not existed.");
    }

    order.getPassengers().size();
    order.getFlights().size();

    return order;

  }

  @Override
  public VasOrder getOrderByOrderNo(int enterpriseId, String orderNo) {
    List<VasOrder> list = em.createQuery("select o from VasOrder o " +
            "where o.enterpriseId = :enterpriseId and o.orderNo = :orderNo", VasOrder.class)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("orderNo", orderNo)
            .getResultList();
    return list.isEmpty() ? null : list.get(0);
  }


  private List<Predicate> buildPredicate_searchVasOrders(CriteriaBuilder cb, CriteriaQuery<VasOrder> cq, Root<VasOrder> root,
                                                         final int enterpriseId, final String username,
                                                         final SearchFlightOrderCriteria sc, final boolean isAdmin,
                                                         List<Integer> allowedCustomerIds) {

    List<Predicate> predicates = new ArrayList<>();

    Predicate predicate = cb.conjunction();
    predicates.add(predicate);

    predicate = cb.equal(root.get(VasOrder_.enterpriseId), enterpriseId);
    predicates.add(predicate);

    predicate = cb.notEqual(root.get(VasOrder_.productType), TieInProduct.INSURANCE);
    predicates.add(predicate);

    if (sc.getStatus() > -1) {
      predicate = cb.equal(root.get(VasOrder_.status), sc.getStatus());
      predicates.add(predicate);
    }

    if (sc.getOrderNo().length() > 0) {
      predicate = cb.equal(root.get(VasOrder_.orderNo), sc.getOrderNo());
      predicates.add(predicate);
    }

    if (sc.getStatus() == -1 && sc.getOrderNo().length() == 0) {
      predicate = cb.notEqual(root.get(VasOrder_.status), TmsOrderConstant.ORDER_STATUS_CANCELED);
      predicates.add(predicate);
    }

    if (sc.getBeginDate() != null) {
      predicate = cb.greaterThanOrEqualTo(root.get(VasOrder_.createDate), sc.getBeginDate());
      predicates.add(predicate);
    }

    if (sc.getEndDate() != null) {
      predicate = cb.lessThanOrEqualTo(root.get(VasOrder_.createDate), sc.getEndDate());
      predicates.add(predicate);
    }

    if (sc.getCustomerId() == 0) {
      predicate = cb.equal(root.get(VasOrder_.customerType), 0);
      predicates.add(predicate);
    } else if (sc.getCustomerId() > 0) {
      predicate = cb.equal(root.get(VasOrder_.customer), sc.getCustomerId());
      predicates.add(predicate);
    }

    if (sc.getProductCode() != null && sc.getProductCode().trim().length() > 0) {
      predicate = cb.equal(root.get(VasOrder_.productCode), sc.getProductCode());
      predicates.add(predicate);
    }

    if (!isAdmin) {
      //非管理员，指定的产品代码只能查看自己创建和处理的

      //已完成的只能查看自己相关的
      predicate = cb.equal(root.get(VasOrder_.operator), username);
      predicate = cb.or(predicate, cb.equal(root.get(VasOrder_.ticketer), username));
      predicate = cb.and(predicate, cb.equal(root.get(VasOrder_.status), TmsOrderConstant.ORDER_STATUS_DONE));
      //可以查看所有未完成的
      predicate = cb.or(predicate, cb.notEqual(root.get(VasOrder_.status), TmsOrderConstant.ORDER_STATUS_DONE));

      predicates.add(predicate);
    }

    if (sc.getOrderType() == 1) {
      predicate = cb.equal(root.get(VasOrder_.orderType), 1);
      predicates.add(predicate);
    } else {
      predicate = cb.isNull(root.get(VasOrder_.orderType));
      predicate = cb.or(predicate, cb.equal(root.get(VasOrder_.orderType), 0));
      predicates.add(predicate);
    }

    if (sc.getOp1() != null && sc.getOp1().trim().length() > 0) {
      predicate = cb.equal(root.get(VasOrder_.operator), sc.getOp1());
      predicates.add(predicate);
    }


    if (allowedCustomerIds != null && allowedCustomerIds.size() > 0) {
      // 只允许查看指定的企业客户的订单
      predicate = cb.in(root.get(VasOrder_.customer).get("id")).value(allowedCustomerIds);
      predicates.add(predicate);
    }

    return predicates;
  }

  /**
   * 查找服务订单
   *
   * @param enterpriseId
   * @param username
   * @param sc
   * @param allowedCustomerIds
   * @return
   */
  @Override
  public List<VasOrder> searchVasOrders(final int enterpriseId, final String username,
                                        final SearchFlightOrderCriteria sc, final boolean isAdmin,
                                        List<Integer> allowedCustomerIds) {
    List<VasOrder> results = null;

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<VasOrder> cq = cb.createQuery(VasOrder.class);
    Root<VasOrder> root = cq.from(VasOrder.class);
    root.alias("o");

    var predicates0 = buildPredicate_searchVasOrders(cb, cq, root, enterpriseId, username, sc, isAdmin, allowedCustomerIds);

    //计算根据条件查询得出的数据总数
    CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
    Root<VasOrder> countRoot = countQuery.from(VasOrder.class);
    countRoot.alias("o");

    var predicates1 = buildPredicate_searchVasOrders(cb, cq, countRoot, enterpriseId, username, sc, isAdmin, allowedCustomerIds);


    // count items
    countQuery.select(cb.count(countRoot)).where(predicates1.toArray(new Predicate[predicates1.size()]));
    Long count = em.createQuery(countQuery).getSingleResult();

    //查询
    cq.select(root).where(predicates0.toArray(new Predicate[predicates0.size()]));

    List<Order> orderByes = new ArrayList<>();
    orderByes.add(cb.desc(root.get("id")));

    cq.orderBy(orderByes);

    int maxResults = count.intValue();
    if (maxResults > 0) {
      sc.getPage().setRowCount(maxResults);

      results = em.createQuery(cq)
              .setFirstResult(sc.getPage().getFirstPosition())
              .setMaxResults(sc.getPage().getPageSize())
              .getResultList();

      for (VasOrder order : results) {
        order.getPassengers().size();
        order.getFlights().size();
      }
    }

    if (results == null) {
      results = new ArrayList<>();
    }

    return results;
  }

  private List<Predicate> buildPredicate_searchInsuranceOrders(CriteriaBuilder cb, CriteriaQuery<VasOrder> cq, Root<VasOrder> root,
                                                               int enterpriseId, SearchFlightOrderCriteria sc, List<Integer> allowedCustomerIds) {

    List<Predicate> predicates = new ArrayList<>();

    Predicate predicate = cb.conjunction();
    predicates.add(predicate);

    predicate = cb.equal(root.get(VasOrder_.enterpriseId), enterpriseId);
    predicates.add(predicate);

    predicate = cb.equal(root.get(VasOrder_.productType), TieInProduct.INSURANCE);
    predicates.add(predicate);

    if (sc.getCustomerId() == 0) {
      // 散客
      predicate = cb.equal(root.get(VasOrder_.customerType), 0);
      predicates.add(predicate);
    } else if (sc.getCustomerId() > 0) {
      // 企业客户（企业散客）
      predicate = cb.equal(root.get(VasOrder_.customer), sc.getCustomerId());
      predicates.add(predicate);
    }

    if (allowedCustomerIds != null && !allowedCustomerIds.isEmpty()) {
      // 只允许查看指定的企业客户的订单
      predicate = cb.in(root.get(VasOrder_.customer).get("id")).value(allowedCustomerIds);
      predicates.add(predicate);
    }

    if (sc.getStatus() > -1) {
      predicate = cb.equal(root.get(VasOrder_.status), sc.getStatus());
    } else {
      //默认不查看已取消订单
      predicate = cb.notEqual(root.get(VasOrder_.status), TmsOrderConstant.ORDER_STATUS_CANCELED);
    }
    predicates.add(predicate);

    if (sc.getBeginDate() != null && sc.getEndDate() != null) {
      predicate = cb.greaterThanOrEqualTo(root.get(VasOrder_.createDate), sc.getBeginDate());
      predicate = cb.and(predicate, cb.lessThanOrEqualTo(root.get(VasOrder_.createDate), sc.getEndDate()));
      predicates.add(predicate);
    } else if (sc.getBeginDate() != null) {
      predicate = cb.greaterThanOrEqualTo(root.get(VasOrder_.createDate), sc.getBeginDate());
      predicates.add(predicate);
    } else if (sc.getEndDate() != null) {
      predicate = cb.lessThanOrEqualTo(root.get(VasOrder_.createDate), sc.getEndDate());
      predicates.add(predicate);
    }

    if (sc.getOrderNo().length() > 0) {
      predicate = cb.equal(root.get(VasOrder_.orderNo), sc.getOrderNo());
      predicates.add(predicate);
    }

    if (sc.getOp1() != null && sc.getOp1().trim().length() > 0) {
      predicate = cb.equal(root.get(VasOrder_.operator), sc.getOp1());
      predicates.add(predicate);
    }

    // 子查询：按照被保险人名字查询
    Subquery<VasOrderPassenger> subQuery = null;
    boolean b = sc.getName() != null && sc.getName().trim().length() > 0;

    if (b) {
      subQuery = cq.subquery(VasOrderPassenger.class);
      Root<VasOrderPassenger> subRoot = subQuery.from(VasOrderPassenger.class);
      subQuery.select(subRoot);
      subQuery.alias("s");

      List<Predicate> subQueryPredicates = new ArrayList<>();
      subQueryPredicates.add(cb.equal(root.get(VasOrder_.id), subRoot.get(VasOrderPassenger_.order)));

      if (sc.getName() != null && sc.getName().trim().length() > 0) {
        subQueryPredicates.add(cb.like(subRoot.get(VasOrderPassenger_.name), "%" + sc.getName().trim() + "%"));
      }

      subQuery.where(subQueryPredicates.toArray(new Predicate[]{}));
    }

    if (subQuery != null) {
      predicates.add(cb.exists(subQuery));
    }

    return predicates;
  }

  /**
   * 查找保险订单
   */
  @Override
  public List<VasOrder> searchInsuranceOrders(int enterpriseId, SearchFlightOrderCriteria sc, List<Integer> allowedCustomerIds) {
    List<VasOrder> results = null;

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<VasOrder> cq = cb.createQuery(VasOrder.class);
    Root<VasOrder> root = cq.from(VasOrder.class);
    root.alias("o");

    var predicates0 = buildPredicate_searchInsuranceOrders(cb, cq, root, enterpriseId, sc, allowedCustomerIds);


    //计算根据条件查询得出的数据总数
    CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
    Root<VasOrder> countRoot = countQuery.from(VasOrder.class);
    countRoot.alias("o");

    var predicates1 = buildPredicate_searchInsuranceOrders(cb, cq, countRoot, enterpriseId, sc, allowedCustomerIds);

    // count items
    countQuery.select(cb.count(countRoot)).where(predicates1.toArray(new Predicate[predicates1.size()]));
    Long count = em.createQuery(countQuery).getSingleResult();

    //查询
    cq.select(root).where(predicates0.toArray(new Predicate[predicates0.size()]));

    List<Order> orderByes = new ArrayList<>();
    orderByes.add(cb.desc(root.get("id")));

    cq.orderBy(orderByes);

    int maxResults = count.intValue();
    if (maxResults > 0) {
      sc.getPage().setRowCount(maxResults);

      results = em.createQuery(cq)
              .setFirstResult(sc.getPage().getFirstPosition())
              .setMaxResults(sc.getPage().getPageSize())
              .getResultList();

      for (VasOrder order : results) {
        order.getPassengers().size();
      }
    }

    if (results == null) {
      results = new ArrayList<>();
    }

    return results;
  }

  @Override
  public List<OperationLog> searchVasOrderHistory(int enterpriseId, int orderId) {
    return searchOrderHistory(enterpriseId, OPERATING_OBJECT_VAS_ORDER, orderId);
  }

  @Override
  public int updateVasOrderRemark(int enterpriseId, String username, int orderId, String remark) {
    int retCode = em.createQuery("update VasOrder o set " +
            "o.remark = :remark " +
            "where o.id = :id and o.enterpriseId = :enterpriseId")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("remark", remark)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = OperationLogFactory.createVasOrderOperationLog();
      log.setEnterpriseId(enterpriseId);
      log.setOrderId(orderId);
      log.setOperator(username);
      log.setContent("备注修改为：" + remark);

      em.persist(log);
    }

    return retCode;
  }

  /**
   * 修改服务订单的供应商
   *
   * @param enterpriseId
   * @param username
   * @param orderId
   * @param supplier
   * @return
   */
  @Override
  public int updateSupplier(int enterpriseId, String username, int orderId, Supplier supplier, PaymentMethod pm) {
    int retCode = em.createQuery("update VasOrder o set " +
            "o.supplier = :supplier, o.paymentMethod = :pm " +
            "where o.id = :id and o.enterpriseId = :enterpriseId")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("supplier", supplier)
            .setParameter("pm", pm)
            .executeUpdate();
    if (retCode != 1) {
      throw new RuntimeException("It failed to update vas order\'s supplier");
    }

    String remark = "修改供应商为:" + supplier.getName() + ", 支付方式为:";
    if (pm == null) {
      remark += "null.";
    } else {
      remark += pm.getName() + ".";
    }

    OperationLog log = createVasOrderLog(enterpriseId, orderId, username, remark);
    em.persist(log);

    return retCode;
  }

  private OperationLog createVasOrderLog(int enterpriseId, int orderId, String username, String s) {
    OperationLog log = OperationLogFactory.createVasOrderOperationLog();
    log.setEnterpriseId(enterpriseId);
    log.setOrderId(orderId);
    log.setOperator(username);
    log.setContent(s);

    return log;
  }

  @Override
  public int cancelVasOrder(int enterpriseId, String username, int orderId, String remark) {
    int retCode = em.createQuery("update VasOrder o set " +
            "o.status = :newStatus " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and (o.status = :oldStatus1 or o.status = :oldStatus2)")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("oldStatus1", TmsOrderConstant.ORDER_STATUS_WAITING)
            .setParameter("oldStatus2", TmsOrderConstant.ORDER_STATUS_PROCESSING)
            .setParameter("newStatus", TmsOrderConstant.ORDER_STATUS_CANCELED)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = OperationLogFactory.createVasOrderOperationLog();
      log.setEnterpriseId(enterpriseId);
      log.setOrderId(orderId);
      log.setOperator(username);

      String memo = "取消订单";
      if (remark != null && remark.trim().length() > 0) {
        memo += " ( " + remark + " )";
      }
      log.setContent(memo);

      em.persist(log);
    }

    return retCode;
  }

  @Override
  public int processVasOrder(int enterpriseId, String username, int orderId, String remark) {
    int retCode = 0;


    retCode = em.createQuery("update VasOrder o set " +
            "o.status = :newStatus, o.ticketer = :ticketer " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and o.status = :oldStatus")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("oldStatus", TmsOrderConstant.ORDER_STATUS_WAITING)
            .setParameter("newStatus", TmsOrderConstant.ORDER_STATUS_PROCESSING)
            .setParameter("ticketer", username)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = OperationLogFactory.createVasOrderOperationLog();
      log.setEnterpriseId(enterpriseId);
      log.setOrderId(orderId);
      log.setOperator(username);

      String memo = "开始处理订单";
      if (remark != null) {
        memo += "(" + remark + ")";
      }
      log.setContent(memo);

      em.persist(log);
    }


    return retCode;
  }

  /**
   * 只有处理人才能确认订单完成
   */
  @Override
  public int finishVasOrder(int enterpriseId, String username, int orderId, final String remark) {
    int retCode = 0;


    retCode = em.createQuery("update VasOrder o set " +
            "o.status = :newStatus " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and o.status = :oldStatus and o.ticketer = :username")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("oldStatus", TmsOrderConstant.ORDER_STATUS_PROCESSING)
            .setParameter("username", username)
            .setParameter("newStatus", TmsOrderConstant.ORDER_STATUS_DONE)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = OperationLogFactory.createVasOrderOperationLog();
      log.setEnterpriseId(enterpriseId);
      log.setOrderId(orderId);
      log.setOperator(username);

      String memo = "订单完成(" + remark + ").";
      log.setContent(memo);

      em.persist(log);
    }


    return retCode;
  }

  /**
   * 修改服务单的客人信息
   *
   * @param enterpriseId
   * @param username
   * @param orderId
   * @param psgId
   * @param psgName
   * @param psgIdNo
   * @param psgRemark
   * @return
   */
  @Override
  public int updateVasOrderPassenger(int enterpriseId, String username, int orderId, int psgId, String psgName, String psgIdNo, String psgRemark) {
    int retCode = em.createQuery("update VasOrderPassenger o set " +
            "o.idNo = :idNo, o.remark = :remark, o.name = :psgName " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and o.order.id = :orderId")
            .setParameter("id", psgId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("orderId", orderId)
            .setParameter("idNo", psgIdNo)
            .setParameter("remark", psgRemark)
            .setParameter("psgName", psgName)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = OperationLogFactory.createVasOrderOperationLog();
      log.setEnterpriseId(enterpriseId);
      log.setOrderId(orderId);
      log.setOperator(username);

      String memo = "修改(" + psgId + ", " + psgName + ")备注：" + psgRemark;
      log.setContent(memo);

      em.persist(log);
    }

    return retCode;
  }

  @Override
  public int updateVasOrderPassengerSeatNo(int enterpriseId, String username, int orderId,
                                           int psgId, String psgName, String seatNo) {
    int retCode = em.createQuery("update VasOrderPassenger o set " +
            "o.seatNo = :seatNo " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and o.order.id = :orderId")
            .setParameter("id", psgId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("orderId", orderId)
            .setParameter("seatNo", seatNo)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = OperationLogFactory.createVasOrderOperationLog();
      log.setEnterpriseId(enterpriseId);
      log.setOrderId(orderId);
      log.setOperator(username);

      String memo = "修改(" + psgName + ")座位号：" + seatNo;
      log.setContent(memo);

      em.persist(log);
    }

    return retCode;
  }

  @Override
  public int updateVasOrderPaid(int enterpriseId, String username, int orderId, String remark) {
    int retCode = 0;


    retCode = em.createQuery("update VasOrder o set " +
            "o.payStatus = 1 " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and o.status = :oldStatus")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("oldStatus", TmsOrderConstant.ORDER_STATUS_PROCESSING)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = OperationLogFactory.createVasOrderOperationLog();
      log.setEnterpriseId(enterpriseId);
      log.setOrderId(orderId);
      log.setOperator(username);

      String memo = "订单已付款：" + remark;
      log.setContent(memo);

      em.persist(log);
    }


    return retCode;
  }

  @Override
  public int updateVasOrderPrice(int enterpriseId, String username, int orderId, double price, double discount, double cost) {
    VasOrder vasOrder = em.find(VasOrder.class, orderId);
    if (vasOrder == null || vasOrder.getEnterpriseId() != enterpriseId) {
      return -1;
    }

    vasOrder.setPrice(price);
    vasOrder.setDiscount(discount);
    vasOrder.setCost(cost);
    vasOrder.calc();

    em.merge(vasOrder);

    var log = OperationLogFactory.createVasOrderOperationLog();
    log.setEnterpriseId(enterpriseId);
    log.setOrderId(orderId);
    log.setOperator(username);

    var memo = "修改订单价格(价格=" + price + ", 折扣=" + discount + ", 成本=" + cost + ")";
    log.setContent(memo);

    em.persist(log);


    return vasOrder.getId();
  }

  @Override
  public int updatePaymentMethod(int enterpriseId, String username, int orderId, PaymentMethod o) {
    int retCode = 0;


    retCode = em.createQuery("update VasOrder o set o.paymentMethod = :paymentMethod, o.lastUpdate = :lastUpdate " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and o.status <> :status")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("paymentMethod", o)
            .setParameter("lastUpdate", DateUtil.getCurDateTime())
            .setParameter("status", TmsOrderConstant.ORDER_STATUS_DONE)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = OperationLogFactory.createVasOrderOperationLog();
      log.setEnterpriseId(enterpriseId);
      log.setOrderId(orderId);
      log.setOperator(username);

      String memo = "支付方式更改为：" + o.getName();
      log.setContent(memo);

      em.persist(log);
    }


    return retCode;
  }

  /**
   * 回滚订单状态
   *
   * @param enterpriseId
   * @param username
   * @param orderId
   * @return
   */
  @Override
  public int rollbackVasOrderStatus(final int enterpriseId, final String username, final int orderId, final String remark) {
    VasOrder o = em.find(VasOrder.class, orderId);
    if (o == null || o.getEnterpriseId() != enterpriseId) {
      throw new RuntimeException("VasOrder is not existed.");
    }

    if (o.getStatus() != TmsOrderConstant.ORDER_STATUS_DONE) {
      throw new RuntimeException("VasOrder status can not be rollback.");
    }

    // 已完成 -> 处理中
    int retCode = em.createQuery("update VasOrder o set o.status = :newStatus, o.lastUpdate = :lastUpdate " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and o.status = :oldStatus")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("oldStatus", TmsOrderConstant.ORDER_STATUS_DONE)
            .setParameter("newStatus", TmsOrderConstant.ORDER_STATUS_PROCESSING)
            .setParameter("lastUpdate", DateUtil.getCurDateTime())
            .executeUpdate();
    if (retCode != 1) {
      throw new RuntimeException("can not update change order status");
    }

    OperationLog log = createVasOrderLog(enterpriseId, orderId, username, "状态回滚为处理中: " + remark);
    em.persist(log);

    return retCode;
  }

  /**
   * 查找已完成，未核销的服务单
   *
   * @param max
   * @return
   */
  @Override
  public List<VasOrder> searchUnpaidOrders(int max) {
    return em.createQuery("select o from VasOrder o " +
            "where (o.payStatus is null or o.payStatus <> 2) " +
            "and o.status = :status " +
            "and o.createTime >= :createTime " +
            "order by o.id desc", VasOrder.class)
            .setParameter("status", TmsOrderConstant.ORDER_STATUS_DONE)
            .setParameter("createTime", getMinBeginDate())
            .setMaxResults(max)
            .getResultList();
  }

  @Override
  public int setOrderWriteOff(int enterpriseId, String username, int id, String remark) {
    int retCode = em.createQuery("update VasOrder o set " +
            "o.payStatus = 2 " +
            "where o.id = :id and o.enterpriseId = :enterpriseId and (o.payStatus is null or o.payStatus <> 2)")
            .setParameter("id", id)
            .setParameter("enterpriseId", enterpriseId)
            .executeUpdate();

    if (retCode == 1) {
      OperationLog log = createVasOrderLog(enterpriseId, id, username, "已销账：" + remark);

      em.persist(log);
    }


    return retCode;
  }

  @Override
  public List<VasOrder> searchByFlightOrderId(int enterpriseId, int flightOrderId) {
    return em.createQuery("select o from VasOrder o " +
            "where o.enterpriseId = :enterpriseId " +
            "and o.flightOrderId = :flightOrderId " +
            "and o.status <> :status order by o.productName", VasOrder.class)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("flightOrderId", flightOrderId)
            .setParameter("status", TmsOrderConstant.ORDER_STATUS_CANCELED)
            .getResultList();
  }

  @Override
  public int updateVaasOrderExternalOrderNo(int enterpriseId, String agentName, int orderId,
                                            String orderNos) {
    int retCode = em.createQuery("update VasOrder o set o.externalOrderNo = :orderNo "
            + "where o.id = :id and o.enterpriseId = :enterpriseId ")
            .setParameter("id", orderId)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("orderNo", orderNos)
            .executeUpdate();
    if (retCode == 1) {
      OperationLog log = createVasOrderLog(enterpriseId, orderId, agentName, "接口提交订单成功。");

      em.persist(log);
    }

    return retCode;
  }

  @Override
  public int appendVasOrderLog(int enterpriseId, String username, int vasOrderId, String remark) {
    OperationLog log = createVasOrderLog(enterpriseId, vasOrderId, username, remark);

    em.persist(log);

    return log.getId();
  }
}
